
#include <unistd.h>     
#include <sys/types.h>  
#include <errno.h>      
#include <stdio.h>      
#include <stdlib.h>     
#include <pthread.h>    
#include <string.h>     
#include <semaphore.h>  
#include <gmp.h>
#include <time.h>

void calc_a( void *ptr );
void calc_y(void *ptr);


unsigned prec_bits = 35000000;
sem_t mutex,mutex2,mutex3,mutex4;
unsigned i = 0;
int stop = 0;

int main()
{
    pthread_t thread_a;
    pthread_t thread_y;
    time_t start, end;
    double dif = 0.0;
    mpf_t x;

    mpf_set_default_prec(prec_bits);
    mpf_init_set_ui(x,1);
    sem_init(&mutex, 0, 1);
    sem_init(&mutex2, 0, 0);
    sem_init(&mutex3, 0, 0);    
                       
    pthread_create (&thread_y, NULL, (void *) &calc_y, (void *) x);
    pthread_create (&thread_a, NULL, (void *) &calc_a, (void *) x);
    
    time(&start);
    pthread_join(thread_y, NULL);
    pthread_join(thread_a, NULL);
    time(&end);
    dif = difftime(end,start);
    printf("Time: %2lf\n",dif);
    printf("Iterations: %u\n",i);
    mpf_out_str(stdout,10,10000001,x);
    printf("\n");        
    sem_destroy(&mutex);
    sem_destroy(&mutex2);
    sem_destroy(&mutex3);
    mpf_clear(x);
    exit(0);
} 

void calc_y(void *ptr)
{
    pthread_t thread_b;
    mpf_t *y = ptr;
    mpf_t t;
    mpf_t aux;

    mpf_set_default_prec(prec_bits);
    mpf_init(t);
    mpf_init(aux);
    mpf_sqrt_ui(t,2);
    mpf_sub_ui((*y),t,1);
    
    while(1)
    {
        mpf_set(t,(*y));
        mpf_pow_ui(t,t,4);
        mpf_ui_sub(t,1,t);
        mpf_sqrt(t,t);
        mpf_sqrt(t,t);
        mpf_ui_sub(aux,1,t);
        mpf_add_ui(t,t,1);
        sem_wait(&mutex);
        if(stop >= 1)
        {   
            sem_post(&mutex2);
            pthread_exit(0);
        }

        mpf_div((*y),aux,t);
        sem_post(&mutex2);
    }
    mpf_clear(t);
    mpf_clear(aux);
	pthread_exit(0);
}



void calc_a( void *ptr )
{
	
    pthread_t thread_b;
    mpf_t *y = ptr;
    mpf_t t1;
    mpf_t t2;
    mpf_t a;
    mpf_t aux;

    
    mpf_set_default_prec(prec_bits);
    mpf_init(t1);
    mpf_init(t2);
    mpf_init(a);
    mpf_init(aux);

    mpf_sqrt_ui(t1,2);
    mpf_mul_ui(a,t1,4); 
    mpf_ui_sub(a,6,a);

   while(1)
   {
        sem_wait(&mutex2);
        if(stop >= 1)
        {   
            sem_post(&mutex);
            pthread_exit(0);
        }
        
        mpf_set(aux,*y);
        sem_post(&mutex);
        mpf_add_ui(t2,aux,1);
        mpf_pow_ui(t1,aux,2);
        mpf_add(t1,t1,t2);
        mpf_mul(t1,t1,aux);
        mpf_mul_2exp(t1,t1,(2*i)+3);
        mpf_pow_ui(t2,t2,4);
        mpf_mul(a,a,t2);
        mpf_sub(a,a,t1);
        i++;

        if(i == 11)
        {
            mpf_ui_div(*y,1,a);
            stop++;
        }
        sem_post(&mutex);
   }
   mpf_clear(t1);
   mpf_clear(t2);
   mpf_clear(a);
   mpf_clear(aux);
   pthread_exit(0);
}

